﻿package utils;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class FileUtility {
	
    private static String[] IEBrowserSignals = {"MSIE", "Trident", "Edge"};
    //判断浏览器是否是微软浏览器
    public static boolean isMSBrowser(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        for (String signal : IEBrowserSignals) {
            if (userAgent.contains(signal))
                return true;
        }
        return false;
    }
    
  //下载文件中文乱码解决
    public static String fileNameSolve(HttpServletRequest request,String beforeFileName) throws UnsupportedEncodingException{
    	boolean isMSIE = isMSBrowser(request);
		if (isMSIE) {
			beforeFileName = URLEncoder.encode(beforeFileName, "UTF-8");
        }else {
        	beforeFileName = new String(beforeFileName.getBytes("UTF-8"), "ISO-8859-1");
        }
		return beforeFileName;
    }

	public static String toUtf8String(String source) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < source.length(); i++) {
			char c = source.charAt(i);
			if (c >= 0 && c <= 255) {
				sb.append(c);
			} else {
				byte[] b;
				try {
					b = Character.toString(c).getBytes("UTF-8");
				} catch (Exception ex) {
					System.out.println(ex);
					b = new byte[0];
				}
				for (int j = 0; j < b.length; j++) {
					int k = b[j];
					if (k < 0) {
						k += 256;
					}
					sb.append("%" + Integer.toHexString(k).toUpperCase());
				}
			}
		}
		return sb.toString();
	}

	// 
	public static void outputFile(HttpServletResponse response, File file) {
		FileInputStream in = null;
		ServletOutputStream out = null;
		try {
			in = new FileInputStream(file);
			byte[] bytIn = new byte[(int) file.length()];
			in.read(bytIn, 0, (int) file.length());
			out = response.getOutputStream();
			out.write(bytIn);
			out.flush();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (out != null) {
					out.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if (in != null) {
					in.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	// 
	public static void downLoadFile(HttpServletRequest request,HttpServletResponse response, String filePath, String newName) throws IOException {
		InputStream in = null;
		ServletOutputStream out = null;
		try {
			in = new FileInputStream(filePath);
			response.reset();
			response.setContentType("application/x-msdownload");
			newName = fileNameSolve(request,newName);
			response.addHeader("Content-Disposition", "attachment; filename=\"" + newName + "\"");
			byte[] b = new byte[100];
			int len;
			out = response.getOutputStream();
			while ((len = in.read(b)) > 0) {
				out.write(b, 0, len);
			}
			out.flush();

		} catch (Exception e) {
			response.setContentType("text/html;charset=UTF-8");
			response.getWriter().write("<center><div style='margin: 210px'><h2 style='color:#666666'>对不起，文件未找到</h2><h3>" +
					"<a style='color:#3D95D7' href='#' onclick='history.go(-1)' />返回</a></h3></div></center>");
			e.printStackTrace();
		} finally {
			try {
				if (null != out) {
					out.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if (null != in) {
					in.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	//
	public static void downLoadByte(HttpServletResponse response, byte[] bytes, String newName) {
		OutputStream out = null;
		try {
			// response.reset(); // �ǳ���Ҫ
			newName = URLEncoder.encode(newName, "UTF-8");
			response.setContentType("application/x-msdownload");
			response.setHeader("Content-Disposition", "attachment; filename=" + newName);
			out = response.getOutputStream();
			out.write(bytes);
			out.flush();
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	//
	public static String getFileName(String filePath) {
		if (filePath != null && !filePath.equals("")) {
			String fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
			return fileName.substring(0, fileName.lastIndexOf("."));
		}
		return null;
	}

	// 
	public static String getExtension(String filePath) {
		if (filePath != null && !filePath.equals("")) {
			String fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
			return fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
		}
		return null;
	}

	//
	public static void createFolder(String path) {
		File file = new File(path);
		if (!file.exists()) {
			path = path.substring(0, path.length() - 1);
			FileUtility.createFolder(path.substring(0, path.lastIndexOf(File.separator) + 1));
			file.mkdir();
		}
	}

  

	public static void uploadStream(InputStream is, String filePath) {
		FileUtility.createFolder(filePath.substring(0, filePath.lastIndexOf(File.separator) + 1));
		try {
			FileUtility.output(is, new FileOutputStream(filePath));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void downLoadStream(HttpServletResponse response, InputStream is, String newName) {
		// OutputStream out = null;
		try {
			response.reset();
			newName = URLEncoder.encode(newName, "UTF-8");
			response.setContentType("application/x-msdownload");
			response.setHeader("Content-Disposition", "attachment; filename=" + newName);
			ServletOutputStream os = response.getOutputStream();
			FileUtility.output(is, os);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void output(InputStream is, OutputStream os) {
		try {
			int r;
			byte[] buffer = new byte[1024];
			while ((r = is.read(buffer)) >= 0) {
				os.write(buffer, 0, r);
			}
			os.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (null != is) {
					is.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if (null != os) {
					os.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

 

	// 生成缩略图
	public static void resize(String src, String dest, int width, int hight) throws Exception {
		FileUtility.createFolder(dest.substring(0, dest.lastIndexOf(File.separator) + 1));
		BufferedImage srcImage;
		String imgType = "JPEG";
		if (src.toLowerCase().endsWith(".png")) {
			imgType = "PNG";
		}
		File saveFile = new File(dest);
		File fromFile = new File(src);
		srcImage = ImageIO.read(fromFile);
		if (width > 0 || hight > 0) {
			srcImage = FileUtility.resize(srcImage, width, hight);
		}
		ImageIO.write(srcImage, imgType, saveFile);
	}

	public static BufferedImage resize(BufferedImage source, int targetW, int targetH) {
		// targetW，targetH分别表示目标长和宽
		int type = source.getType();
		BufferedImage target = null;
		if (source.getWidth() > targetW || source.getHeight() > targetH) {
			double sx = (double) targetW / source.getWidth();
			double sy = (double) targetH / source.getHeight();
			// 这里想实现在targetW，targetH范围内实现等比缩放。如果不需要等比缩放
			// 则将下面的if else语句注释即可
			if (sx > sy) {
				sx = sy;
				targetW = (int) (sx * source.getWidth());
			} else {
				sy = sx;
				targetH = (int) (sy * source.getHeight());
			}
			if (type == BufferedImage.TYPE_CUSTOM) { // handmade
				ColorModel cm = source.getColorModel();
				WritableRaster raster = cm.createCompatibleWritableRaster(targetW, targetH);
				boolean alphaPremultiplied = cm.isAlphaPremultiplied();
				target = new BufferedImage(cm, raster, alphaPremultiplied, null);
			} else {
				target = new BufferedImage(targetW, targetH, type);
			}
			Graphics2D g = target.createGraphics();
			// smoother than exlax:
			g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
			g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
			g.dispose();
		} else {
			target = source;
		}
		return target;
	}

	/**
	 * 把图片印刷到图片上
	 */
	public final static void watermark(String watermark, String target) throws Exception {
		// 目标文件
		File _file = new File(target);
		Image src = ImageIO.read(_file);
		int wideth = src.getWidth(null);
		int height = src.getHeight(null);
		BufferedImage image = new BufferedImage(wideth, height, BufferedImage.TYPE_INT_RGB);
		Graphics g = image.createGraphics();
		g.drawImage(src, 0, 0, wideth, height, null);

		// 水印文件
		File _filebiao = new File(watermark);
		Image src_biao = ImageIO.read(_filebiao);
		int wideth_biao = src_biao.getWidth(null);
		int height_biao = src_biao.getHeight(null);
		g.drawImage(src_biao, 0, height - height_biao, wideth_biao, height_biao, null);
		// 水印文件结束
		g.dispose();
		FileOutputStream out = new FileOutputStream(target);
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		encoder.encode(image);
		out.close();
	}

	/**
	 * 生成水印
	 */
	public final static void generateWaterMark(String src, String dest, String watermark) throws Exception {

		File srcFile = new File(src);
		File destFile = new File(dest);
		FileUtils.copyFile(srcFile, destFile);

		// 目标文件
		File _file = destFile;

		Image destImage = ImageIO.read(_file);
		int wideth = destImage.getWidth(null);
		int height = destImage.getHeight(null);
		BufferedImage image = new BufferedImage(wideth, height, BufferedImage.TYPE_INT_RGB);
		Graphics g = image.createGraphics();
		g.drawImage(destImage, 0, 0, wideth, height, null);

		// 水印文件
		File _filebiao = new File(watermark);
		Image src_biao = ImageIO.read(_filebiao);
		int wideth_biao = src_biao.getWidth(null);
		int height_biao = src_biao.getHeight(null);
		g.drawImage(src_biao, 0, height - height_biao, wideth_biao, height_biao, null);
		// 水印文件结束
		g.dispose();
		FileOutputStream out = new FileOutputStream(destFile);
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		encoder.encode(image);
		out.close();
	}

	// 生成缩略图
	public static void generateImageThumb(String src, String dest, int width, int hight) throws Exception {
		FileUtility.createFolder(dest.substring(0, dest.lastIndexOf(File.separator) + 1));
		BufferedImage srcImage;
		String imgType = "JPEG";
		if (src.toLowerCase().endsWith(".png")) {
			imgType = "PNG";
		}
		File saveFile = new File(dest);
		File fromFile = new File(src);
		srcImage = ImageIO.read(fromFile);
		if (width > 0 || hight > 0) {
			srcImage = FileUtility.resize(srcImage, width, hight);
		}
		ImageIO.write(srcImage, imgType, saveFile);
	}

	// 生成缩略图
	public static void generateVideoThumb(String src, String dest, int width, int hight) throws Exception {
		String cmd = "D:\\ffmpeg\\bin\\ffmpeg.exe -i " + src + " -ss 1 -vframes 1 -r 1 -ac 1 -ab 2 -s " + width + "*" + hight + " -f  image2 " + dest;
		try {
			// 调用批处理文件
			Runtime.getRuntime().exec(cmd);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	public static void main(String[] args) {
		try {
			// FileUtility.generateThumb("D:\\3176902_154117631337_2.jpg", "D:\\3176902_154117631337_2_ico.jpg", 120, 100);
			// FileUtility.generateWaterMark("D:\\3176902_154117631337_2.jpg", "D:\\3176902_154117631337_2_pic.jpg", "D:\\3176902_154117631337_2_ico.jpg");
			// FileUtility.generateVideoThumb("D:\\19828399384379292.mp4", "D:\\19828399384379292_ico.jpg", 200, 160);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	//压缩图片
	private static void resizeico(BufferedImage source,String savepath, int ysw,   
            int ysh) throws IOException {    

		Image image = source;
		
		int imageWidth;
		int imageHeight;
		
		double rate1 = ((double) image.getWidth(null))/ (double) ysw ;
		double rate2 = ((double) image.getHeight(null))/ (double) ysh ;
		double rate = rate1 > rate2 ? rate1 : rate2;
		imageWidth = (int) (((double) image.getWidth(null)) / rate);
		imageHeight = (int) (((double) image.getHeight(null)) / rate);

		image = image.getScaledInstance(imageWidth, imageHeight,
				Image.SCALE_AREA_AVERAGING);
		BufferedImage mBufferedImage = new BufferedImage(imageWidth,
				imageHeight, BufferedImage.TYPE_INT_RGB);
		Graphics2D g2 = mBufferedImage.createGraphics();

		g2.drawImage(image, 0, 0, imageWidth, imageHeight, Color.white,
				null);
		g2.dispose();

		float[] kernelData2 = { -0.125f, -0.125f, -0.125f, -0.125f, 2,
				-0.125f, -0.125f, -0.125f, -0.125f };
		Kernel kernel = new Kernel(3, 3, kernelData2);
		ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
		mBufferedImage = cOp.filter(mBufferedImage, null);
		ImageIO.write(mBufferedImage,savepath.substring(savepath.lastIndexOf(".")+1),new File(savepath));
    }    
  //压缩截取图片
    public static boolean compress(InputStream in, File saveFile, String savePath)throws Exception {
    	 BufferedImage srcImage = null;
         try {
             srcImage = ImageIO.read(in);
         } catch (IOException e) {
             e.printStackTrace();
             return false;
         }
         int width = 220; 
         int hight = 220;
         double old_f=(double)srcImage.getWidth()/(double)srcImage.getHeight(); //原图的比例
         if(srcImage.getWidth()>srcImage.getHeight()){//原图是宽图
        	if(old_f<=2.5){ //直接压缩
         		resizeico(srcImage,savePath, width, hight);//宽或者高最大为150
         	}else{//先截取在压缩 从左往右 100:40截取
         		int x=0;
             	int y=0;
             	int w1=(int)(srcImage.getHeight()*2.5);
             	try {
 					srcImage= saveSubImage(srcImage, new Rectangle(x, y, w1, srcImage.getHeight()), saveFile);
 					resizeico(srcImage,savePath, width, hight);//宽或者高最大为150
 				} catch (IOException e) {
 					e.printStackTrace();
 				}
         	}
         	
         }else{//原图是高图
         	if(old_f>=0.4){//直接压缩
         		resizeico(srcImage,savePath, width, hight);//宽或者高最大为150
         	}else{//先截取在压缩 从上往下40:100截取
         		
         		int x=0;
             	int y=0;
             	int h1=(int)(srcImage.getWidth()/0.4);
             	try {
 					srcImage= saveSubImage(srcImage, new Rectangle(x, y, srcImage.getWidth(), h1), saveFile);
 					resizeico(srcImage,savePath, width, hight);//宽或者高最大为150
 				} catch (IOException e) {
 					e.printStackTrace();
 				}
         	}
         } 
         return true;
    }
   //截取图片
    public static BufferedImage saveSubImage(BufferedImage image,    
            Rectangle subImageBounds, File subImageFile) throws IOException {   
        if (subImageBounds.x < 0 || subImageBounds.y < 0   
                || subImageBounds.width - subImageBounds.x > image.getWidth()   
                || subImageBounds.height - subImageBounds.y > image.getHeight()) {     
            return null;    
        }     
        BufferedImage subImage = image.getSubimage(subImageBounds.x,subImageBounds.y, subImageBounds.width, subImageBounds.height); 
        return subImage;
    } 
    //截取并输出
    public static void saveSubImageNew(BufferedImage image,    
            Rectangle subImageBounds, File subImageFile) throws IOException {   
        if (subImageBounds.x < 0 || subImageBounds.y < 0   
                || subImageBounds.width - subImageBounds.x > image.getWidth()   
                || subImageBounds.height - subImageBounds.y > image.getHeight()) {   
         //   LoggerUtil.error(ImageHelper.class, "Bad subimage bounds");    
            return;    
        }     
        BufferedImage subImage = image.getSubimage(subImageBounds.x,subImageBounds.y, subImageBounds.width, subImageBounds.height); 
        String fileName = subImageFile.getName();    
        String formatName = fileName.substring(fileName.lastIndexOf('.') + 1);   
        ImageIO.write(subImage, formatName, subImageFile);
    }
    //将原图转换成缩略图
    public static List<Map<String,Object>> icoImage(List<Map<String, Object>>  list) {
    	if(list.size()!=0){
	    	List<Map<String, Object>> newList = new   ArrayList<Map<String, Object>>();
	    	for( Map<String, Object>  map :list){
				String image = map.get("image")+"";
				if(image!=null){
				    int point = image.lastIndexOf(".");
				    if(point!=-1){
					    String ext = image.substring(point + 1);
						String imageThumbPath = image.substring(0, point) + "_ico." + ext;
						map.put("image", imageThumbPath);
						newList.add(map);
				    }
				}
			}
			return newList;
    	}else{
    		return null;
    	}
	}
	 
}